﻿using DrawTools.Serialize;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace DrawTools.Tools
{
    /// <summary>
    /// 曲线
    /// </summary>
    [SerializerType(typeof(DrawCurveSerializer))]
    public sealed class CurveDrawTool : DrawGeometryBase
    {
        #region 字段

        private List<Point> points = new List<Point>();
        private Point? mousePoint;

        protected override Point BeginingPoint => base.BeginingPoint.X != 0 ? base.BeginingPoint : (pathGeometry?.Figures?.Count > 0 == true ? pathGeometry.Figures[0].StartPoint : new Point());

        #endregion 字段

        public CurveDrawTool(DrawingCanvas drawingCanvas) : base(drawingCanvas)
        {
            DrawingToolType = DrawToolType.Curve;

            // 准备要处理的事件
            CanTouchDown = true;
        }

        #region 鼠标键盘事件

        public override bool OnTouchLeave(Point point, bool isLeaved = false)
        {
            if (mousePoint.HasValue)
            {
                points.Add(mousePoint.Value);
                mousePoint = null;
            }

            if (points.Count < 2)
                drawingCanvas.DeleteVisual(this);
            else
            {
                geometry = geometry.GetWidenedPathGeometry(Pen);
                Draw();
            }

            drawingCanvas.DeleteWorkingDrawTool(this);

            IsFinish = true;

            CanTouchDown = false;
            CanTouchMove = false;
            CanTouchLeave = false;

            if (isLeaved || TouchId == 0 && drawingCanvas.IsMouseCaptured)
                drawingCanvas.ReleaseMouseCapture();

            return true;
        }

        public override bool OnTouchDown(int touchId, Point point)
        {
            TouchId = touchId;

            if (points.Count == 0)
            {
                drawingCanvas.AddWorkingDrawTool(this);

                points.Add(point);

                geometry = new PathGeometry();

                var figure = new PathFigure { StartPoint = point };
                pathGeometry.Figures.Add(figure);

                CanTouchMove = true;

                if (TouchId != 0 || !drawingCanvas.CaptureMouse())
                    CanTouchLeave = true;

                drawingCanvas.AddVisual(this);
            }
            else if ((point - points.Last()).Length <= Pen.Thickness)
                return OnTouchLeave(point);
            else if (mousePoint.HasValue)
            {
                points.Add(mousePoint.Value);
                mousePoint = null;
            }

            return true;
        }

        public override bool OnTouchMove(Point point)
        {
            var last = points.Last();

            if ((point - last).Length <= Pen.Thickness)
                return true;

            var figure = pathGeometry.Figures[0];
            var centerX = (last.X + point.X) / 2;
            var bezier = new BezierSegment(new Point(centerX, last.Y), new Point(centerX, point.Y), point, true) { IsSmoothJoin = true };

            if (mousePoint.HasValue && figure.Segments.Count > 0)
                figure.Segments[figure.Segments.Count - 1] = bezier;
            else
                figure.Segments.Add(bezier);

            mousePoint = point;

            var dc = RenderOpen();
            dc.DrawGeometry(null, Pen, geometry);
            dc.Close();

            return true;
        }

        #endregion 鼠标键盘事件
    }
}